use std::{collections::HashMap, sync::{Arc, Mutex}};

use crate::{classpath::{Classpath, Entry}, classfile::ClassFile, rtda::{Slots, ExtraType}};

use super::{class::Class, field::Field, class_name_helper::PRIMITIVE_TYPES, string_pool, Method};

// 简易类加载器
pub struct ClassLoader {
    cp: Classpath,
    verbose_flag: bool,
    class_map: HashMap<String, Arc<Class>>, // loaded classes
    this: Option<Arc<Mutex<ClassLoader>>>, // 存储自身引用
}

unsafe impl Send for ClassLoader { }

impl ClassLoader {
    pub fn new_class_loader(cp: Classpath, verbose_flag: bool) -> Arc<Mutex<ClassLoader>> {
        let class_loader = Arc::new(Mutex::new(ClassLoader {
            cp,
            verbose_flag,
            class_map: HashMap::new(),
            this: None,
        }));
        let mut loader = class_loader.lock().unwrap();

        loader.this = Some(class_loader.clone());

        loader.load_basic_classes();
        loader.load_primitive_classes();
        drop(loader);
        class_loader
    }

    // 加载基本类型和void类
    fn load_primitive_classes(&mut self) {
        for primitive_type in PRIMITIVE_TYPES.keys() {
            self.load_primitive_class(primitive_type);
        }
    }

    fn load_primitive_class(&mut self, class_name: &str) {
        let class = Class::new_primitive_class(class_name, self.arc());
        let mut j_class = Class::new_object(self.class_map.get("java/lang/Class").unwrap().clone());
        j_class.set_extra(Some(ExtraType::Class(class.clone())));

        // 231027 Class unsafe 此时处于创建过程中，通过unsafe修改内部值是安全的。
        unsafe { &mut *(Arc::as_ptr(&class) as *mut Class) }.set_j_class(Some(Box::into_raw(Box::new(j_class))));

        self.class_map.insert(class_name.to_string(), class.clone());

        // 231117 暂存基础类
        // let map: HashMap<&str, &str> = HashMap::from_iter(
        //     vec![
        //         ("void",    "java/lang/Void"),
        //         ("boolean", "java/lang/Boolean"),
        //         ("byte",    "java/lang/Byte"),
        //         ("short" ,  "java/lang/Short"),
        //         ("int",     "java/lang/Integer"),
        //         ("long",    "java/lang/Lang"),
        //         ("char",    "java/lang/Character"),
        //         ("float",   "java/lang/Float"),
        //         ("double",  "java/lang/Double"),
        //     ].into_iter()
        // );
        // self.class_map.insert(map.get(class_name).unwrap().to_string(), class);
    }

    fn load_basic_classes(&mut self) {
        // 先加载java.lang.Class类，这又会触发java.lang.Object等类和接口的加载。
        let jl_class_class = self.load_class("java/lang/Class".to_string());
        // 然后遍历classMap，给已经加载的每一个类关联类对象
        for class in self.class_map.values() {
            if class.get_j_class().is_none() {
                let mut j_class = Class::new_object(jl_class_class.clone());
                j_class.set_extra(Some(ExtraType::Class(class.clone())));
                // 231027 Class unsafe 此时处于创建过程中，通过unsafe修改内部值是安全的。
                unsafe { &mut *(Arc::as_ptr(class) as *mut Class) }.set_j_class(Some(Box::into_raw(Box::new(j_class))));
            }
        }
    }

    // 加载类到方法区
    pub fn load_class(&mut self, name: String) -> Arc<Class> {
        if self.class_map.contains_key(&name) {
            return self.class_map.get(&name).unwrap().clone();
        }
        let class = if name.starts_with("[") { self.load_array_class(name) }
                                else { self.load_non_array_class(name) };
        if let Some(jl_class_class) = self.class_map.get("java/lang/Class") {
            let mut j_class = Class::new_object(jl_class_class.clone());
            j_class.set_extra(Some(ExtraType::Class(class.clone())));
            // 231027 Class unsafe 此时处于创建过程中，通过unsafe修改内部值是安全的。
            unsafe { &mut *(Arc::as_ptr(&class) as *mut Class) }.set_j_class(Some(Box::into_raw(Box::new(j_class))));
        }
        class
    }

    // 加载数组类
    fn load_array_class(&mut self, name: String) -> Arc<Class> {
        let mut class = Class::new_array_class(name.clone(), self.arc());
        // 将添加super_class于interfaces放到此方法进行
        let super_class = self.load_class("java/lang/Object".to_string());
        class.set_super_class(super_class);
        let cloneable = self.load_class("java/lang/Cloneable".to_string());
        let serializable = self.load_class("java/io/Serializable".to_string());
        let interfaces = vec![cloneable, serializable];
        class.set_interfaces(interfaces);
        let class = Arc::new(class);
        self.class_map.insert(name, class.clone());
        class
    }

    // 加载非数组类
    fn load_non_array_class(&mut self, name: String) -> Arc<Class> {
        // TODO read_class 要返回字节数据，和具体的Entry引用，目前Entry引用仅打印使用，暂不添加。
        let data = self.read_class(&name);
        let class = self.define_class(data);
        // let mut class = unsafe { &mut *ptr };
        self.link(class.clone());
        if self.verbose_flag {
            println!("[loaded {} from xxx_entry]", name);
        }
        self.class_map.insert(class.get_name(), class.clone());
        class
    }

    // 读取Class， 返回class文件字节码
    fn read_class(&mut self, name: &str) -> Vec<u8> {
                let result = self.cp.read_class(name);
                match result {
            Ok(data) => data,
            Err(e) => panic!("java.lang.ClassNotFoundException: {}", e)
        }
    }

    // 定义Class，data: class文件字节码
    fn define_class(&mut self, data: Vec<u8>) -> Arc<Class> {
        let class = Self::parse_class(data);
        // 231027 Class unsafe 此时处于创建过程中，通过unsafe修改内部值是安全的。
        unsafe {
            let mut class_mut = &mut *(Arc::as_ptr(&class) as *mut Class);
            class_mut.set_class_loader(self.arc());
    
            Self::hack_class(&class_mut);
    
            self.resolve_super_class(&mut class_mut);
            self.resolve_inter_class(&mut class_mut);
        }
        // 换地方插入map
        // self.class_map.insert(class.get_name(), class.clone());
        class
    }

    // 将字节码转换为Class结构体
    fn parse_class(data: Vec<u8>) -> Arc<Class> {
        let result = ClassFile::parse(data);
        match result {
            Ok(cf) => Class::new_class(cf),
            Err(_) => panic!("java.lang.ClassFormatError")
        }
    }

    // 加载超类
    fn resolve_super_class(&mut self, class: &mut Class) {
        let name = class.get_name();
        if name != "java/lang/Object" {
            let super_class_name = class.get_super_class_name();
            let super_class = self.load_class(super_class_name);
            class.set_super_class(super_class);
        }
    }

    // 加载接口
    fn resolve_inter_class(&mut self, class: &mut Class) {
        let interface_names = class.get_interface_names();
        if !interface_names.is_empty() {
            let interfaces = interface_names.iter().map(|name| {
                let interface = self.load_class(name.to_string());
                interface
            }).collect();
            class.set_interfaces(interfaces);
        }
    }

    // 类的链接, 分为验证和准备两个必要阶段
    fn link(&mut self, class: Arc<Class>) {
        // 231027 Class unsafe 此时处于创建过程中，通过unsafe修改内部值是安全的。
        let class = unsafe {&mut *(Arc::as_ptr(&class) as *mut Class)};
        Self::verify(class);
        self.prepare(class);
    }

    // 验证
    #[allow(unused_variables)]
    fn verify(class: &mut Class) {
        // TODO 参考Java虚拟机规范4.10节
    }

    // 准备
    fn prepare(&mut self, class: &mut Class) {
        // 首先，静态字段和实例字段要分开编号，否则会混乱。
        // 其次，对于实例字段，一定要从继承关系的最顶端，也就是java.lang.Object开始编号，否则也会混乱。
        // 最后，编号时也要考虑long和double类型。
        Self::calc_instance_field_slot_ids(class);
        Self::calc_static_field_slot_ids(class);
        self.alloc_and_init_static_vars(class);
    }

    // 计算实例字段的个数，同时给它们编号
    fn calc_instance_field_slot_ids(class: &mut Class) {
        let mut slot_id = 0usize;
        let super_class = class.get_super_class();
        if let Some(sc) = super_class {
            // 从父类的slot编号之后开始。
            slot_id = sc.get_instance_slot_count();
        }
        let fields = class.get_fields(false);
        // TODO 231027 Field unsafe 初始化时修改值。暂未确定是否安全。
        unsafe {
            for item in fields {
                let ptr = Arc::as_ptr(&item) as *mut Field;
                let field = &mut *ptr;
                // 非静态变量
                if !field.is_static() {
                    field.set_slot_id(slot_id);
                    // long或double占两个位置
                    slot_id += if field.is_long_or_double() { 2 } else { 1 };
                }
            }
        }
        class.set_instance_slot_count(slot_id);
    }

    // 计算静态字段的个数，同时给它们编号
    fn calc_static_field_slot_ids(class: &mut Class) {
        let mut slot_id = 0usize;
        let fields = class.get_fields(false);
        // TODO 231027 Field unsafe 初始化时修改值。暂未确定是否安全。
        unsafe {
            for item in fields {
                let ptr = Arc::as_ptr(&item) as *mut Field;
                let field = &mut *ptr;
                // 静态变量
                if field.is_static() {
                    field.set_slot_id(slot_id);
                    // long或double占两个位置
                    slot_id += if field.is_long_or_double() { 2 } else { 1 };
                }
            }
        }
        class.set_static_slot_count(slot_id);
    }

    // 给类变量分配空间，然后给它们赋予初始值
    fn alloc_and_init_static_vars(&mut self, class: &mut Class) {
        // 初始化静态变量，默认初始值（数字类型是0，引用类型是null）
        class.set_static_vars(Slots::new_slots(class.get_static_slot_count()));
        let fields = class.get_fields(false);
        for field in fields {
            // 如果静态变量属于基本类型或String类型，有final修饰符，且它的值在编译期已知，则该值存储在class文件常量池中。
            if field.is_static() && field.is_final() {
                self.init_static_final_var(class, field);
            }
        }
    }

    // 从常量池中加载常量值，然后给静态变量赋值
    fn init_static_final_var(&mut self, class: &mut Class, field: Arc<Field>) {
        let cp = class.get_constant_pool().unwrap();
        let cp_index = field.get_const_value_index();
        let vars = class.get_static_vars();
        let mut vars = vars.write().unwrap();
        let slot_id = field.get_slot_id();
        // 根据descriptor判断类型，再根据cp_index从常量池中获取值，将获取到的值放入class staticVars中
        if cp_index > 0 {
            match &field.get_descriptor()[..] {
                "Z" | "B" | "C" | "S" | "I" => {
                    let val = cp.get_constant(cp_index).unwrap().int();
                    vars.set_int(slot_id, val);
                },
                "J" => {
                    let val = cp.get_constant(cp_index).unwrap().long();
                    vars.set_long(slot_id, val);
                },
                "F" => {
                    let val = cp.get_constant(cp_index).unwrap().float();
                    vars.set_float(slot_id, val);
                },
                "D" => {
                    let val = cp.get_constant(cp_index).unwrap().double();
                    vars.set_double(slot_id, val);
                },
                "Ljava/lang/String;" => {
                    let rs_str = cp.get_constant(cp_index).unwrap().string();
                    let j_str = string_pool::j_string(self, &rs_str);
                    vars.set_ref(slot_id, Some(j_str));
                },
                _ => panic!("fn init_static_final_var error")
            }
        }
    }

    // TODO 跳过java/lang/ClassLoader.loadLibrary方法
    fn hack_class(class: &Class) {
        if class.get_name().as_str() == "java/lang/ClassLoader" {
            let load_libiary = class.get_static_method("loadLibrary", "(Ljava/lang/Class;Ljava/lang/String;Z)V").unwrap();
            // 231027 Method unsafe 此处是安全的。
            unsafe {
                let ptr = Arc::as_ptr(&load_libiary) as *mut Method;
                let method = &mut *ptr;
                method.set_code(vec![0xb1]); // return
            }
        }

        // TODO 231212 CallSite初始化出现死循环，未找到解决方法，暂时跳过初始化方法
        if class.get_name().as_str() == "java/lang/invoke/CallSite" {
            let load_libiary = class.get_static_method("<clinit>", "()V").unwrap();
            // 231027 Method unsafe 此处是安全的。
            unsafe {
                let ptr = Arc::as_ptr(&load_libiary) as *mut Method;
                let method = &mut *ptr;
                method.set_code(vec![0xb1]); // return
            }
        }
        // if class.get_name().as_str() == "java/lang/invoke/LambdaForm" {
        //     let load_libiary = class.get_static_method("computeInitialPreparedForms", "()V").unwrap();
        //     // 231027 Method unsafe 此处是安全的。
        //     unsafe {
        //         let ptr = load_libiary.as_ref() as *const Method as *mut Method;
        //         let method = &mut *ptr;
        //         method.set_code(vec![0xb1]); // return
        //     }
        // }

        // 231216 为方便测试线程，暂时跳过此类初始化方法，此方法 while true 无限循环 守护线程
        // if class.get_name().as_str() == "java/lang/ref/Reference" {
        //     let load_libiary = class.get_static_method("<clinit>", "()V").unwrap();
        //         // 231027 Method unsafe 此处是安全的。
        //     unsafe {
        //         let ptr = load_libiary.as_ref() as *const Method as *mut Method;
        //         let method = &mut *ptr;
        //         method.set_code(vec![0xb1]); // return
        //     }
        // }
        
        
    }

    // 获取自身arc引用
    fn arc(&self) -> Arc<Mutex<ClassLoader>> {
        self.this.clone().unwrap()
    }

    // 获取已加载的类
    pub fn get_class(&mut self, name: String) -> Option<Arc<Class>> {
        if self.class_map.contains_key(&name) {
            return Some(self.class_map.get(&name).unwrap().clone());
        }
        None
    }
}